dojo.provide("uws.drawing.SurfaceManager");

dojo.declare('uws.drawing.SurfaceManager',null,{
	/*
		Adds, edits, gets, and deletes diagrams from the data store. It also broadcasts properties of the selected diagram.
	*/
	idcounter:null,
	surfaces:null,
	clickTokens:null,
	visibleTab:null,
	surfacesById:null,
	
	constructor:function(start){
		this.idcounter = start,
		this.surfaces = [];
		this.clickTokens = [];
		this.surfacesById = [];
	},
	openSurface:function(item){
		var temp = this.getSurface(dataStore.getValue(item, "id"));
		var type = dataStore.getValue(item, "umltype");
		var href = "";
		
		if(type=="usecase"){
			href="page_components/usecase_toolbar.html";
		}else if(type=="activity"){
			href="page_components/activity_toolbar.html";
		}else if(type=="sequence"){
			href="page_components/sequence_toolbar.html";
		}else if(type=="classdiagram"){
			href="page_components/class_toolbar.html";
		}else if(type=="sqlerd"){
			href="page_components/sqlerd_toolbar.html";
		}
		
		if(temp!=null && temp!=undefined){
			surfaceManager.focus(temp);
			return;
		}
		
		var id = dataStore.getValue(item, "id");
		var suffix = generateID(id);
		
		var tab = new dijit.layout.ContentPane({
			id: "tab_"+suffix,
			title: dataStore.getValue(item, "name"),
			closable:true
		});
		
		var border = new dijit.layout.BorderContainer({
			width:"100%",
			height:"100%"
		});
		
		border.addChild(new dijit.layout.ContentPane({
			href: href,
			region:"top",
			preload:true
		}));
		
		border.addChild(new dijit.layout.ContentPane({
			id:"canvas_" + suffix,
			region:"center"
		}));
		
		tab.set('content', border);
		
		dijit.byId("tabContainer").addChild(tab);
		var surface = new dojox.gfx.createSurface(dojo.byId("canvas_"+suffix),item.width[0], item.height[0]);
		
		surface.id=id;
		surface.name=item.name[0];
		surface.type=item.umltype[0];
		surface.containerId="canvas_"+suffix;
		surface.containerTabId="tab_"+suffix;
		
		var clickToken = dojo.connect(surface._parent,"onclick",null,function(e){
			if(drawManager.drawing) drawManager.drawNow(e);
			else if(e.target.localName == "svg" || e.target.localName=="div"){
				componentFocusManager.unfocus();
				surfaceManager._publishProperties();
			}
		});
		
		this.surfaces[surface.containerTabId] = surface;
		this.surfacesById[surface.id] = surface;
		this.clickTokens[surface.containerTabId] = clickToken;
		
		surface.whenLoaded(function(surface){
			surfaceManager.focus(surface);
			dataStore.fetchItemByIdentity({
				identity: surface.id,
				scope: this,
				onItem: function(item){
					var comp = dataStore.getValues(item, "children");
					
					sortOrderManager.addSurface(dataStore.getValue(item, "id"), dataStore.getValue(item, "sort_order"));
					for(var i=0;i<comp.length;i++){				//bubble sort
						for(var j=0;j<comp.length;j++){
							if(dataStore.getValue(comp[i], "sortOrder") < dataStore.getValue(comp[j], "sortOrder")){
								var temp = comp[i];
								comp[i] = comp[j];
								comp[j] = temp;
							}
						}
					}
					
					for(var i=0;i<comp.length;i++){
						drawManager.drawFromDataStore(item,comp[i]);
						
						if(i==comp.length-1){
							componentFocusManager.focus(comp[i]);
						}
						//sometimes the components are not in the same position
					}
					
					var conn = dataStore.getValues(item,"connections");
					for(var i=0;i<conn.length;i++){
						try{
							connectionHandler.connectionFromDataStore(
								dataStore.getValue(conn[i], "id"),
								dataStore.getValue(conn[i], "umltype"),
								componentManager.getById(dataStore.getValue(conn[i], "ref1_id")),
								dataStore.getValue(conn[i], "ref1_dir"),
								componentManager.getById(dataStore.getValue(conn[i], "ref2_id")),
								dataStore.getValue(conn[i], "ref2_dir"),
								dataStore.getValue(conn[i], "stereotype"),
								dataStore.getValue(conn[i], "custom"),
								dataStore.getValue(conn[i], "cardinality1"),
								dataStore.getValue(conn[i], "cardinality2"),
								surface
							);
						}catch(e){
							console.debug(e.name + ": "+ e.message);
						}
					}
				}
			});
		});
	},
	newSurface:function(id, diagramName, diagramType, tab, tabId){
		try{
			var surface = new dojox.gfx.createSurface(dojo.byId(id),5000, 5000);
			var clickToken = dojo.connect(surface._parent,"onclick",null,function(e){
				if(drawManager.drawing) drawManager.drawNow(e);
				else if(e.target.localName == "svg" || e.target.localName=="div"){
					componentFocusManager.unfocus();
					surfaceManager._publishProperties();
				}
			});
			surface.id="diagram_"+this.idcounter;
			surface.name=diagramName;
			surface.type=diagramType;
			surface.containerId="canvas_"+id;
			surface.containerTabId=tabId;
			
			sortOrderManager.addSurface(surface.id);
			this.surfaces[tabId] = surface;
			this.surfacesById[surface.id] = surface;
			this.clickTokens[tabId] = clickToken;
			surface.whenLoaded(function(){
				dijit.byId("tabContainer").selectChild(tab);
				var item = dataStore.newItem(
					{
						id: surface.id,
						name: diagramName,
						uwstype: 'diagram',
						umltype: diagramType,
						width: 5000,
						height: 5000,
						sort_order: 0,
						custom: '',
						description: '',
						children:[],
						connections:[]
					}, {
						parent : root,
						attribute: 'children'
					}
				);
				
				dataStore.setValue(root,"diag_counter", ++surfaceManager.idcounter);
				surfaceManager.focus(surface);
			});
			return surface.id;
		}catch(e){
			console.debug("Error Creating Surface:")
			console.dir(e);
		}
		return null;
	},
	getVisibleSurface:function(){
		if(this.visibleTab==null) return null;
		try{
			return this.surfaces[this.visibleTab];
		}catch(e){
			return null;
		}
	},
	getSurface:function(id){
		try{
			return this.surfacesById[id];
		}catch(e){
			return null;
		}
	},
	setVisibleSurface:function(tab){
		this.visibleTab=tab;
	},
	removeItem:function(id,isTabId, removeComponent, forceCloseTab){
		console.debug("Remove: "+id+" isTabId: "+isTabId);
		
		if(forceCloseTab){
			if(isTabId){
				if(this.surfaces[id]==null) return;
				var tab = dijit.byId(this.surfaces[id].containerTabId);
				dijit.byId("tabContainer").removeChild(tab);
			}else{
				if(this.surfacesById[id]==null) return;
				var tab = dijit.byId(this.surfacesById[id].containerTabId);
				dijit.byId("tabContainer").removeChild(tab);
			}
		}
		
		if(isTabId){
			if(this.surfaces[id]==null) return;
			sId = this.surfaces[id].id;
			//remove components from view
			dataStore.fetchItemByIdentity({
				identity: sId,
				onItem: function(item){
					dojo.forEach(dataStore.getValues(item, "children"), function(childItem) {
						componentManager.removeItem(dataStore.getValue(childItem, "id"));
					});
				}
			});
			
			if(sId==propertiesManager.currentItem){
				dojo.byId("propertiesName").innerHTML = '';
				dojo.byId("propertiesDiv").innerHTML = '<span style="font-style:italic">Please select an item.</span>';
				propertiesManager.currentItem = null;
			}
			
			dojo.disconnect(this.clickTokens[id]);
			this.surfaces[id].destroy();
			
			delete(this.clickTokens[id]);
			delete(this.surfaces[id]);
			delete(this.surfacesById[sId]);
		}else{
			if(this.surfacesById[id]==null) return;
			
			if(id==propertiesManager.currentItem){
				dojo.byId("propertiesName").innerHTML = '';
				dojo.byId("propertiesDiv").innerHTML = '<span style="font-style:italic">Please select an item.</span>';
				propertiesManager.currentItem = null;
			}
			
			//remove components from view
			dataStore.fetchItemByIdentity({
				identity: id,
				onItem: function(item){
					dojo.forEach(dataStore.getValues(item, "children"), function(childItem) {
						componentManager.removeItem(dataStore.getValue(childItem, "id"));
					});
				}
			});
			
			tabId = this.surfacesById[id].containerId;
			dojo.disconnect(this.clickTokens[tabId]);
			this.surfaces[tabId].destroy();
			
			delete(this.surfaces[tabId]);
			delete(this.clickTokens[tabId]);
			delete(this.surfacesById[id]);
		}
		this.setVisibleSurface(null);
	},
	destroyItem:function(id,isTabId){
		//destroy components first
		dataStore.fetchItemByIdentity({
			identity: id,
			onItem: function(item){
				dojo.forEach(dataStore.getValues(item, "children"), function(childItem) {
					componentManager.destroyItem(dataStore.getValue(childItem, "id"));
				});
			}
		});
		
		this.removeItem(id,isTabId, false, true);			//do not remove components. they are already destroyed
		console.debug("Destroy: "+id);
		dataStore.fetchItemByIdentity({
			identity: id,
			onItem: function(item){
				dataStore.deleteItem(item);
			}
		});
	},
	focus:function(surface){
		dijit.byId("tabContainer").selectChild(dijit.byId(surface.containerTabId));
	},
	_publishProperties:function(item){
		//TODO: retitle container tab
		if(item!=null){
			var attr = dataStore.getAttributes(item);
			var val = [];
			for(var i=0;i<attr.length;i++){
				val[i] = dataStore.getValue(item, attr[i], "");
			}
			dojo.publish("uwsProperties",[{
				attributes:attr,
				values:val
			}]);
		}else if(this.getVisibleSurface()!=null){
			var surface = this.getVisibleSurface();
			
			dataStore.fetchItemByIdentity({
				identity: surface.id,
				scope: surfaceManager,
				onItem:function(component){
					var attr = dataStore.getAttributes(component);
					var val = [];
					for(var i=0;i<attr.length;i++){
						val[i] = dataStore.getValue(component, attr[i], "");
					}
					dojo.publish("uwsProperties",[{
						attributes:attr,
						values:val
					}]);
				},
				onError:function(error){
					console.debug(error);
				}
			});
		}
	}
});